#ifndef __MACROS_H__
#define __MACROS_H__

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)

#define PLACEHOLDER(NodeTypeName)                  \
    template <typename T, auto member = &T::visit> \
    struct NodeTypeName                            \
    {                                              \
        std::string type = #NodeTypeName;          \
        using PlaceholderType = std::invoke_result_t<decltype(member), T>;

#define CHECK_TYPE_HAS_VISIBLE_PROPERTY_NAME(PropertyName)     \
    template <typename AnyParams>                              \
    struct Check##PropertyName                                 \
    {                                                          \
        typedef char one;                                      \
        struct two                                             \
        {                                                      \
            char x[2];                                         \
        };                                                     \
        template <typename C>                                  \
        static one test(decltype(&C::PropertyName));           \
        template <typename C>                                  \
        static two test(...);                                  \
                                                               \
    public:                                                    \
        enum                                                   \
        {                                                      \
            value = sizeof(test<AnyParams>(0)) == sizeof(char) \
        };                                                     \
    };

#define DISALLOW_ASSIGN(TypeName) TypeName &operator=(const TypeName &) = delete;

#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
    TypeName(const TypeName &) = delete;   \
    DISALLOW_ASSIGN(TypeName)

#define MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(TypeName) \
    TypeName() = default;                             \
    MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeName)

#define MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeName) \
    TypeName(TypeName &&) = default;               \
    TypeName &operator=(TypeName &&) = default;    \
    DISALLOW_COPY_AND_ASSIGN(TypeName)

#define DECLARE_STATIC_STRING_AND_INIT(x, y) \
    namespace cyclone::parser                \
    {                                        \
        static constexpr char *x = y;        \
    };                                       \
    using cyclone::parser::x

#define DECLARE_STATIC_STRING_WITH_DEFAULT(x) \
    namespace cyclone::parser                 \
    {                                         \
        static constexpr char *x = #x;        \
    };                                        \
    using cyclone::parser::x

#define SAFE_DELETE(x) \
    if (x)             \
        delete x;      \
    x = nullptr;
#endif // __MACROS_H__